﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Telerik.WinControls;
using Telerik.WinControls.Data;
using Telerik.WinControls.UI;
using MN.Framework.Common;
using MN.Framework.Common.Service;
using MN.Framework.Extensions;
using MN.Framework.UI.Win.Controls;

namespace MN.Framework.UI.Win
{
    public class MnGridView<EntityType> : RadGridView where EntityType : BaseEntity
    {
        private MnGridView(BaseContext context, IBaseView<EntityType> winView, BaseEntity entity)
        {
            Context = context;
            SetUIProperties();
            this.RowValidating += TzGridView_RowValidating;

            if (entity == null)
                Entity = Context.Set<EntityType>().Create();
            else
                Entity = entity;

            if (winView == null)
                EntityColumns = ServiceFactory.GetColumns(Entity);
            else
                EntityColumns = winView.GetColumns();

            Api.MasterGridColumnsGenerator<EntityType>(this.Columns, EntityColumns, this, Entity, context);

            DataBind();
        }
        public MnGridView(BaseContext context, BaseEntity entity = null)
            : this(context, null, entity)
        {
        }
        public MnGridView(BaseContext context, IBaseView<EntityType> winView)
            : this(context, winView, null)
        {
        }

        #region Peroperty
        BaseContext Context { get; set; }
        BaseEntity Entity { get; set; }
        #endregion

        public List<ColumnInfo> EntityColumns { get; set; }


        public void SetUIProperties()
        {
            this.RightToLeft = System.Windows.Forms.RightToLeft.Yes;
            this.BackColor = System.Drawing.Color.Black;
            this.Dock = DockStyle.Fill;
            this.AutoGenerateColumns = false;
            this.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill;
            //this.ShowFilteringRow = true;           
            //this.EnableFiltering = true;
            this.SelectionMode = GridViewSelectionMode.FullRowSelect;
            this.CellEditorInitialized += gridview_CellEditorInitialized;
        }

        public void DataBind()
        {
            if (Entity == null)
                this.DataSource = Context.Set<EntityType>().ToList();
            else
                this.DataSource = Context.Set(Entity.GetType()).AsEnumerable();
        }

        protected override void OnCreateControl()
        {
            base.OnCreateControl();
            this.RowsChanged += gridview_RowsChanged;
        }

        void TzGridView_RowValidating(object sender, RowValidatingEventArgs e)
        {
            //var columns = ServiceFactory.girdColumns(Entity);
            foreach (var Column in Columns)
            {
                if (Column.ReadOnly)
                    continue;

                if (e.Row != null && e.Row.Cells[Column.Name].Value != null)
                {
                    var type = EntityColumns.SingleOrDefault(c => c.Name == Column.Name).BaseType;
                    if (Entity == null)//---if generated by EntityType----
                        typeof(EntityType).GetProperty(Column.Name).
                                  SetValue(Entity, Convert.ChangeType(e.Row.Cells[Column.Name].Value, type));
                    else
                        Entity.GetType().GetProperty(Column.Name).
                                  SetValue(Entity, Convert.ChangeType(e.Row.Cells[Column.Name].Value, type));
                }
            }


            //for (int i = 0; i < columns.Count; i++)
            //{
            //    if (columns[i].Name != "ID")
            //    {
            //        var type = columns[i].BaseType;
            //        if (e.Row != null && e.Row.Cells[columns[i].Name].Value != null)
            //        {
            //            if (Entity == null)//---if generated by EntityType----
            //                typeof(EntityType).GetProperty(columns[i].Name).
            //                          SetValue(Entity, Convert.ChangeType(e.Row.Cells[columns[i].Name].Value, type));
            //            else
            //                Entity.GetType().GetProperty(columns[i].Name).
            //                          SetValue(Entity, Convert.ChangeType(e.Row.Cells[columns[i].Name].Value, type));
            //        }
            //    }
            //}

            //if (!Entity.Validate())
            //{
            //    var error = Entity.GetErrorMessages();
            //    System.Windows.Forms.RightToLeft rtl = System.Windows.Forms.RightToLeft.Yes;
            //    if (Telerik.WinControls.RadMessageBox.Show(this, error + "\n " + "می خواهید ادامه دهید؟", "خطا", MessageBoxButtons.RetryCancel, Telerik.WinControls.RadMessageIcon.Info, MessageBoxDefaultButton.Button1, rtl) == DialogResult.Cancel)
            //    {
            //        // DataBind();
            //        try
            //        {
            //            if (e.Row.Cells["ID"].Value == "0")
            //                e.Row.Delete();
            //        }
            //        catch { }
            //    }
            //    else
            //    {
            //        e.Cancel = true;
            //        e.Row.ErrorText = error;
            //    }
            //}
        }

        //void ColumnsGenerator<EntityType>(GridViewColumnCollection Columns, object Entity) where EntityType : class
        //{
        //    if (Columns.Any())
        //        return;
        //    List<ColumnInfo> columns;
        //    if (Entity == null)
        //        columns = ServiceFactory.getColumns<EntityType>();
        //    else
        //        columns = ServiceFactory.getColumns<EntityType>(Entity);

        //    var smallWidth = this.Width / columns.Select(c => (int)c.Size).Sum();

        //    foreach (var clmn in columns)
        //    {
        //        if (clmn.Type == ColumnType.Image)
        //        {
        //            GridViewImageColumn img = new GridViewImageColumn(clmn.Name);
        //            img.HeaderText = clmn.HeaderText;
        //            img.ImageLayout = ImageLayout.Stretch;
        //            img.ImageAlignment = System.Drawing.ContentAlignment.MiddleCenter;
        //            img.NullValue = ResourceImages.user;
        //            Columns.Add(img);
        //        }
        //        else if (clmn.Type == ColumnType.Refrence)
        //        {
        //            #region filter
        //            FilterDescriptor filterComboBox = new FilterDescriptor();
        //            filterComboBox.PropertyName = "Name";
        //            filterComboBox.Operator = FilterOperator.Contains;
        //            filterComboBox.Value = "";
        //            filterComboBox.IsFilterEditor = true;
        //            this.FilterDescriptors.Add(filterComboBox);
        //            #endregion

        //            #region GridViewMultiComboBoxColumn
        //            GridViewMultiComboBoxColumn lookup = new GridViewMultiComboBoxColumn(clmn.Name);
        //            lookup.DisplayMember = "Name";
        //            lookup.ValueMember = "ID";
        //            lookup.Name = clmn.Name;
        //            lookup.CustomDataOperation = CustomDataOperation.Filtering;
        //            lookup.AllowFiltering = true;
        //            lookup.Width = 150;
        //            lookup.StretchVertically = true;
        //            Columns.Add(lookup);

        //            //lookup.FilterDescriptor = filterComboBox;                    
        //            //lookup.AutoCompleteMode = AutoCompleteMode.Suggest;
        //            #endregion

        //            #region GridViewComboBoxColumn
        //            //GridViewComboBoxColumn lookup = new GridViewComboBoxColumn(clmn.Name);
        //            //lookup.DataSource = Context.RelationEntity<EntityType>(clmn.Name);
        //            //lookup.DisplayMember = "Name";
        //            //lookup.ValueMember = "ID";
        //            //lookup.HeaderText = clmn.HeaderText;
        //            //lookup.AllowFiltering = true;
        //            //lookup.FilteringMode = GridViewFilteringMode.DisplayMember;
        //            //lookup.FilterDescriptor = filterComboBox;
        //            //lookup.Width = 150;
        //            //lookup.AutoCompleteMode = AutoCompleteMode.Suggest;
        //            //lookup.WrapText = true;
        //            #endregion

        //        }
        //        else if (clmn.Type == ColumnType.Numeric)
        //        {
        //            GridViewMaskBoxColumn mtxt = new GridViewMaskBoxColumn(clmn.Name);
        //            mtxt.MaskType = MaskType.Numeric;
        //            mtxt.HeaderText = clmn.HeaderText;
        //            mtxt.Name = clmn.Name;
        //            Columns.Add(mtxt);
        //        }
        //        else
        //        {
        //            GridViewTextBoxColumn txt = new GridViewTextBoxColumn(clmn.Name);
        //            txt.HeaderText = clmn.HeaderText;
        //            txt.Name = clmn.Name;
        //            Columns.Add(txt);
        //        }
        //        //---check readonly----              
        //        Columns.Last().ReadOnly = clmn.ReadOnly;
        //        Columns.Last().Width = clmn.Width(smallWidth);
        //    }                        
        //    DataGridViewButtonColumn btn = new DataGridViewButtonColumn();
        //    //btn.Text = "ذخیره تغییرات";
        //    //btn.ContextMenuStrip.Click += ContextMenuStrip_Click;
        //    //Columns.Add(btn);
        //}

        void ContextMenuStrip_Click(object sender, EventArgs e)
        {
            throw new NotImplementedException();
        }
        //void LoadData<EntityType>(GridViewRowCollection rows, object Entity = null) where EntityType : class
        //{
        //    if (rows.Any())
        //        return;
        //    List<ColumnInfo> columns;
        //    IEnumerable<object> dbrows;
        //    if (Entity == null)
        //    {
        //        var dbset = Context.Set<EntityType>();
        //        dbrows = dbset.AsEnumerable();
        //        columns = ServiceFactory.getColumns<EntityType>(Entity);
        //    }
        //    else
        //    {
        //        var dbset = Context.Set(Entity.GetType());
        //        dbrows = dbset.AsEnumerable();
        //        columns = ServiceFactory.getColumns<EntityType>(Entity);
        //    }

        //    foreach (var dbrow in dbrows)
        //    {
        //        try
        //        {
        //            GridViewRowInfo row = rows.AddNew();
        //            for (int i = 0; i < columns.Count; i++)
        //            {
        //                //if (columns[i].ColumnType == typeof(string))
        //                row.Cells[i].Value = dbrow.GetType().GetProperty(columns[i].Name).GetValue(dbrow);
        //            }
        //        }
        //        catch { }
        //    }
        //}
        void gridview_RowsChanged(object sender, GridViewCollectionChangedEventArgs e)
        {
            //var entityColumns = ServiceFactory.getColumns<EntityType>();
            if (e.Action == Telerik.WinControls.Data.NotifyCollectionChangedAction.ItemChanged)
            {
                var ID = int.Parse(this.CurrentRow.Cells["ID"].Value.ToString());
                //if (Entity == null)
                //Entity = Context.Set<EntityType>().Find(ID);
                foreach (var clmn in EntityColumns)
                {
                    if (this.Rows[e.NewStartingIndex].Cells[clmn.Name].ColumnInfo.Name != "ID")
                    {
                        if (this.Rows[e.NewStartingIndex].Cells[clmn.Name].ColumnInfo is Telerik.WinControls.UI.GridViewMultiComboBoxColumn)
                        {
                            if (clmn.Type != ColumnType.Refrence)
                                typeof(EntityType).GetProperty(clmn.Name).
                                           SetValue(Entity, Convert.ChangeType(this.Rows[e.NewStartingIndex].Cells[clmn.Name].Value, clmn.BaseType));
                            else
                                typeof(EntityType).GetProperty(clmn.Name).
                                  SetValue(Entity, Convert.ChangeType(this.Rows[e.NewStartingIndex].Cells["hidden_" + clmn.Name].Value, clmn.BaseType));
                        }
                        if (this.Rows[e.NewStartingIndex].Cells[clmn.Name].ColumnInfo is MnSelector)
                        {
                            typeof(EntityType).GetProperty(clmn.Name).
                                           SetValue(Entity, Convert.ChangeType(this.Rows[e.NewStartingIndex].Cells[clmn.Name].Value, clmn.BaseType));
                        }
                        else
                            typeof(EntityType).GetProperty(clmn.Name).
                                       SetValue(Entity, Convert.ChangeType(this.Rows[e.NewStartingIndex].Cells[clmn.Name].Value, clmn.BaseType));
                    }
                }

                Context.SaveChanges();
            }
            else if (e.Action == Telerik.WinControls.Data.NotifyCollectionChangedAction.Add)
            {
                //if (Entity == null)
                //    Entity = Context.Set<EntityType>().Create();
                foreach (var clmn in EntityColumns)
                {
                    if (this.Rows[e.NewStartingIndex].Cells[clmn.Name].ColumnInfo.Name != "ID")
                    {
                        if (clmn.Type != ColumnType.Refrence)
                        {
                            typeof(EntityType).GetProperty(clmn.Name).
                                    SetValue(Entity, Convert.ChangeType(this.Rows[e.NewStartingIndex].Cells[clmn.Name].Value, clmn.BaseType));
                        }
                        else if (this.Rows[e.NewStartingIndex].Cells["hidden_" + clmn.Name].Value != null)
                        {
                            typeof(EntityType).GetProperty(clmn.Name).
                                  SetValue(Entity, Convert.ChangeType(this.Rows[e.NewStartingIndex].Cells["hidden_" + clmn.Name].Value, clmn.BaseType));
                        }
                    }
                }
                Context.Set<EntityType>().Add(Entity as EntityType);
                Context.SaveChanges();
            }
            else if (e.Action == Telerik.WinControls.Data.NotifyCollectionChangedAction.Remove)
            {
                if (this.CurrentRow.Cells["ID"].Value == null)
                {
                    return;
                }
                var ID = int.Parse(this.CurrentRow.Cells["ID"].Value.ToString());
                EntityType obj = Context.Set<EntityType>().Find(ID);
                Context.Set<EntityType>().Remove(obj);
                Context.SaveChanges();
            }
        }
        void gridview_CellEditorInitialized(object sender, GridViewCellEventArgs e)
        {
            RadMultiColumnComboBoxElement multiComboElement = this.ActiveEditor as RadMultiColumnComboBoxElement;
            if (multiComboElement != null)
            {
                EditoInitialized(multiComboElement);
                multiComboElement.SelectedIndexChanged += multiComboElement_SelectedIndexChanged;
                multiComboElement.BeginEdit();
            }
        }

        void multiComboElement_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (((RadMultiColumnComboBoxElement)(sender)).SelectedValue != null)
                this.CurrentRow.Cells["hidden_" + ((RadMultiColumnComboBoxElement)(sender)).Name].Value = ((RadMultiColumnComboBoxElement)(sender)).SelectedValue;
        }
        void EditoInitialized(RadMultiColumnComboBoxElement multiComboElement)
        {
            multiComboElement.Name = this.CurrentColumn.Name;
            //----make columns----
            multiComboElement.Columns.Clear();
            var list = Context.RelationEntity<EntityType>(multiComboElement.Name).ToList();
            var obj = list.First();
            Api.DetailGridColumnsGenerator<EntityType>(multiComboElement.Columns, this.Width, obj as BaseEntity, Context);
            var columnsCount = multiComboElement.Columns.Count;
            multiComboElement.DataSource = list;

            ///----*****---Delete Auto Generated Columns---*****----
            if (multiComboElement.Columns.Count > columnsCount)
            {
                var allColumnsCount = multiComboElement.Columns.Count;
                for (int c = 0; c < allColumnsCount - columnsCount; c++)
                    multiComboElement.Columns.RemoveAt(multiComboElement.Columns.Count - 1);
            }

            multiComboElement.DisplayMember = (obj as BaseEntity).FirstOrDefaultDisplayField();
            multiComboElement.PopupOpening -= new CancelEventHandler(element_PopupOpening);

            multiComboElement.DropDownStyle = RadDropDownStyle.DropDownList;
            multiComboElement.AutoFilter = true;
            multiComboElement.DropDownHeight = this.Height / 2;
            multiComboElement.DropDownWidth = this.Width / 2;
            multiComboElement.TextChanged += multiComboElement_TextChanged;
            if (multiComboElement.EditorControl.MasterGridViewTemplate.FilterExpressions.Count == 0)
            {
                FilterExpression autoFilter = new FilterExpression(multiComboElement.DisplayMember, FilterExpression.BinaryOperation.AND,
                    GridKnownFunction.StartsWith, GridFilterCellElement.ParameterName);
                autoFilter.Parameters.Add(GridFilterCellElement.ParameterName, string.Empty);
                multiComboElement.EditorControl.MasterGridViewTemplate.FilterExpressions.Add(autoFilter);
            }
        }

        string lastText = string.Empty;
        string lastValue = string.Empty;
        void multiComboElement_TextChanged(object sender, EventArgs e)
        {
            var multiComboElement = sender as RadMultiColumnComboBoxElement;
            if (!multiComboElement.EditorControl.MasterGridViewTemplate.FilterExpressions.Any())
                EditoInitialized(multiComboElement);

            string propertyName = multiComboElement.EditorControl.MasterGridViewTemplate.FilterExpressions[0].PropertyName;
            string propertyValue = multiComboElement.Text.Trim();

            if (multiComboElement.Value == null || multiComboElement.Value != lastValue)
                if (!string.IsNullOrEmpty(propertyValue) && (string.IsNullOrEmpty(lastText) || !lastText.Contains(propertyValue)))
                {
                    multiComboElement.DataSource = Context.RelationEntity<EntityType>(multiComboElement.Name).WhereQuery(propertyName, propertyValue).ToList();
                    lastText = propertyValue;
                    if (multiComboElement.Value != null)
                        lastValue = multiComboElement.Value.ToString();
                }

        }
        void element_PopupOpening(object sender, CancelEventArgs e)
        {
            RadMultiColumnComboBoxElement element = sender as RadMultiColumnComboBoxElement;
            element.MultiColumnPopupForm.MinimumSize = new Size(this.Width / 2, this.Height / 2);
            element.MultiColumnPopupForm.RightToLeft = System.Windows.Forms.RightToLeft.Yes;
            element.MultiColumnPopupForm.HorizontalPopupAlignment = HorizontalPopupAlignment.RightToLeft;
            element.EditorControl.GridViewElement.MinSize = new Size(this.Width / 2, this.Height / 2);
            element.MultiColumnPopupForm.Width = this.Width / 2;

        }
    }
}
